package cn.gemframe.security.filter;

import java.io.IOException;
import java.util.Collection;
import java.util.List;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.gemframe.config.security.GemTokenProperties;
import cn.gemframe.constant.GemConstant;
import cn.gemframe.common.constant.RequestPath;
import cn.gemframe.exception.status.GemErrorStatus;
import cn.gemframe.response.ResultData;
import cn.gemframe.utils.GemJsonUtils;
import cn.gemframe.utils.GemReqJsonUtils;
import cn.gemframe.utils.GemStringUtlis;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.http.HttpStatus;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.filter.OncePerRequestFilter;

import com.google.common.collect.Lists;

import lombok.Data;
import lombok.EqualsAndHashCode;

@Data
@Slf4j
@EqualsAndHashCode(callSuper = false)
public class GemUserLoginValidateFilter extends OncePerRequestFilter {
	private Environment env;
	private TokenStore tokenStore;
	private GemTokenProperties gemTokenProperties;
	private ValueOperations<String, Object> valueOperations;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
	    log.info("---init gemuserloginvalidatefilter");
		//统一设置
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType(GemConstant.MediaType.JSON_UTF_8);
        String requestURI = request.getRequestURI();
        //判空
		if(requestURI == null){
            response.getWriter().write(GemJsonUtils.objectToJson(ResultData.getIllegalArgumentResult()));
			return;
		}

		//刷新token，用户登录，手机登录，登录错误,用户登出
		if (requestURI.equals(RequestPath.Auth.LOGIN)
				|| requestURI.equals(RequestPath.Auth.LOGOUT)
				|| requestURI.equals(RequestPath.Auth.ERROR)
				|| requestURI.equals(RequestPath.Auth.REFRESH_TOKEN)
		) {
			//是否开启token有效期开关
			boolean isOpenExpir = gemTokenProperties.isOpenExpir();
			if (!isOpenExpir && requestURI.equalsIgnoreCase(RequestPath.Auth.LOGIN)) {
                String username = request.getParameter("username");
                if(username == null || GemStringUtlis.isBlank(username)){
                    username = request.getParameter("phone");
                    if(username == null || GemStringUtlis.isBlank(username)){
                        username = request.getParameter("email");
                        if(username == null || GemStringUtlis.isBlank(username)){
                            username = request.getParameter("appid");
                            if(username == null || GemStringUtlis.isBlank(username)){
                                response.getWriter().write(GemJsonUtils.objectToJson(ResultData.getIllegalArgumentResult()));
                                return;
                            }
                        }
                    }
                }
				List<OAuth2AccessToken> list = Lists.newArrayList();
				Collection<OAuth2AccessToken> tokens =
						tokenStore.findTokensByClientIdAndUserName(GemConstant.Auth.CLIENT_ID_NAME, username);
				tokens.forEach(token -> list.add(token));
				for (OAuth2AccessToken oAuth2AccessToken : tokens) {
					String value = oAuth2AccessToken.getValue();
					valueOperations.set(value, value);
					tokenStore.removeAccessToken(oAuth2AccessToken);
					tokenStore.removeRefreshToken(oAuth2AccessToken.getRefreshToken());
				}
			}
			filterChain.doFilter(request, response);
		}else{
			log.error("---error uri:{}",requestURI);

            response.getWriter().write(GemJsonUtils.objectToJson
                    (ResultData.getResultWithCode(GemErrorStatus.METHOD_ERROR)));
			return;
		}
	}

}
